﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.MathLib
{

    /// <summary>
    /// 圆锥体
    /// </summary>
    public class Cone3d : Solid3d
    {
        private double radius;
        private double height;

        public double Radius { get => radius; set => SetSize(value, height); }
        public double Height { get => height; set => SetSize(radius, value); }

        public static int TempSegments = 50;

        public Cone3d() { }
        public Cone3d(double radius, double height)
        {
            this.SetSize(radius, height);
        }

        public Surface3d[] Surfaces;
        private TopoFaceModel topoFaceModel;
        public Cone3d SetSize(double radius, double height)
        {
            if (topoFaceModel != null && (this.radius != radius || this.height != height))
            {
                topoFaceModel = null;
            }
            this.radius = radius;
            this.height = height;
            return this;
        }

        private Vector3 topVertex; //圆锥体/圆锥台 顶部点
        private List<Vector3> btmVertexes; //圆锥体/圆锥台 底部轮廓点
        public override TopoFaceModel CreateTopoModel()
        {
            if (topoFaceModel != null)
                return topoFaceModel;

            topVertex = new Vector3(0, 0, height);

            var conicalFace1 = new ConicalSurface3d(radius, height, 0, Utils.PI, false);
            var conicalFace2 = new ConicalSurface3d(radius, height, Utils.PI, Utils.TwoPI, false);
            var surfaces = new List<Surface3d>()
            {
                conicalFace1,
                conicalFace2,
            };

            var btmCurve = new Circle3d(radius);
            btmCurve.UseFixedDiv(Cone3d.TempSegments * 2);
            btmVertexes = btmCurve.GetPoints();

            var btmFace = new PlanarSurface3d(new Plane(new Vector3(0, 0, -1)), new List<Curve3d> { btmCurve });
            surfaces.Add(btmFace);

            this.Surfaces = surfaces.ToArray();
            this.topoFaceModel = new TopoFaceModel() { Surfaces = this.Surfaces.ToListEx() };

            return this.topoFaceModel;
        }

        public override Solid3d CreateMesh()
        {
            base.CreateMesh();

            var idxsCount = this.Geometry.Indics.Length;
            var aroundIdxCount = btmVertexes.Count * 3;
            var btmIdxCount = idxsCount - aroundIdxCount;

            this.Geometry.Groups = new GeometryGroup[2]
            {
                new GeometryGroup{ Name = "Around", Start = 0, Count = aroundIdxCount, MaterialIndex = 0 },
                new GeometryGroup{ Name = "Bottom", Start = aroundIdxCount, Count = btmIdxCount, MaterialIndex = 1}
            };
            this.Edge = new GeometryData();
            var v3Array = new double[3 * (btmVertexes.Count + 1)];
            topVertex.ToArray(v3Array, 0);

            var idxArray = new ListEx<int>() { 0, 1 };
            var btmIdxArray = new ListEx<int>();
            for (int i = 0; i < btmVertexes.Count; i++)
            {
                var nxi = (i + 1) % btmVertexes.Count;
                btmVertexes[i].ToArray(v3Array, (i + 1) * 3);

                btmIdxArray.Push(i + 1, nxi + 1);
            }
            idxArray = idxArray.Concat(btmIdxArray);
            
            this.Edge.Verteics = v3Array;
            this.Edge.Indics = idxArray.ToArray();
            return this;
        }
    }
}